package com.example.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpHeaders;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author zhy
 * @version 1.0.0
 * @ClassName TrimReqParamWrapper.java
 * @Description 处理http请求参数带空格
 * @createTime 2021年08月05日 11:19:00
 */
public class TrimReqParamWrapper extends HttpServletRequestWrapper {

    private static final Logger logger = LoggerFactory.getLogger(TrimReqParamWrapper.class);

    public TrimReqParamWrapper(HttpServletRequest request) {
        super(request);
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        logger.info("请求参数去空格处理");
        // 非json类型直接返回
        if (!super.getHeader(HttpHeaders.CONTENT_TYPE).equalsIgnoreCase(MediaType.APPLICATION_JSON_VALUE)) {
            return super.getInputStream();
        }
        // 从输入流中取出body串，如果为空，直接返回
        String reqBodyStr = IOUtils.toString(super.getInputStream(), "utf-8");
        if (StringUtils.isEmpty(reqBodyStr)) {
            return super.getInputStream();
        }
        logger.info("转化前request body:{}", reqBodyStr);
        // reqBodyStr转为map
        Map<String, Object> paramMap = new ObjectMapper().readValue(reqBodyStr, new TypeReference<HashMap<String, Object>>() {});
        Map<String, Object> trimedMap = recursiveTrim(paramMap);
        logger.info("转化后request body：{}", JSONObject.toJSONString(trimedMap));
        //重新构造一个输入流对象
        byte[] bytes = JSON.toJSONString(trimedMap).getBytes("utf-8");
        ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
        return new MyServletInputStream(bis);
    }

    private Map<String, Object> recursiveTrim(Map<String, Object> paramMap) {
        for (String key : paramMap.keySet()) {
            Object obj = paramMap.get(key);
            if (null == obj) {
                continue;
            }
            if (obj instanceof String) {
                paramMap.put(key, StringUtils.trimToEmpty((String) obj));
            } else if (obj instanceof Map) {
                paramMap.put(key, recursiveTrim((Map<String, Object>) obj));
            } else if (obj instanceof List) {
                List<Object> list = (List<Object>) obj;
                for (int i = 0; i < list.size(); i++) {
                    Object o = list.get(i);
                    if (o instanceof String) {
                        list.set(i, StringUtils.trimToEmpty((String) o));
                    } else if (o instanceof Map) {
                        list.set(i, recursiveTrim((Map<String, Object>) o));
                    }
                }
                paramMap.put(key, obj);
            }
        }
        return paramMap;
    }

    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }
}
